$Revision: 1.2 $

 Notes techniques sur le mecanisme du systeme de "build"


 ## unites de bases :

  * taskItem (une tache)
    Structure de donnees definissant une action (exceution de commande).
    Sauf cas exceptionnel, une tache ne definit qu'une seule action.
    les taches definissent des methodes permettant de stocker/restaurer
    leurs donnees vers/a partir d'une liste.
    
    
  ** proprietes
    
    Toutes les taches definissent des proprietes suivantes :
    
      string tasktype   : type de la tache
    
    Le type de la tache est definit sous forme de chaine; le propriete
    "tasktype" est utile pour gerer la compatibilite entre taches de types
    differents. Le type est defini a la creation de la tache est n'est pas
    modifiable (lecture seule).
    
      bool   enabled    : etat (actif/desactiv) de la tache
      string logfile    : fichier de traces (log)
      string comments   : commentaires relative a l'action de la tache
    
    Une tache desactiv (enabled = False) ne peut passer de commande. Le
    "logfile" est utilis pour stocker les messages renvoys par le systeme
    a l'issu de l'execution de l'action.
    Les commentaires donnent quelques infos supplementaires.
    "logfile" et/ou "comments" peuvent etre de valeur nulle (None).
   
      list   attributes : liste des proprietes reconnues
      dict   miscvalues : les "autres" proprietes
    
    Chaque type de tache definit des attributs supplementaires affectables
    et qui lui sont generalement propres; chaque nom de ces proprietes est
    retenu par la liste "attributes". C'est la liste des proprietes "cls"
    d'une tache (pas forcement obligatoires).
    
    e.g. un "taskItem" de base 'aTask'
      aTask.attributes
      => ['enabled', 'logfile', 'comments']
    
    "miscvalues" correspond aux proprietes "non attendues" recuperees a
    partir d'une liste; c'est la partie "variable" des donnees.
    
    
  ** methodes speciales
    
    Les taches definissent les methodes "speciales" suivantes :
    
      bool   __nonzero__(void)
    
    Indique si la tache est "vide", une tache "vide" n'a aucune de ses
    proprietes (hormis "enabled" qui est TOUJOURS definie) definies, toutes
    les proprietes sont de valeur nulles (None). Une tache "vide" est par
    essence non valide.
    
      string __str__(void)
    
    Retourne une representation simplifiee de la commande qui sera passee
    au systeme. Il n'y a pas de garantie que la chaine retournee soit une
    commande acceptee par le systeme, neamoins elle doit etre suffisemment
    informative.
    
   
  ** methodes
    
    Toutes les taches definissent les methodes suivantes :
    
      void   debug(int tab)
      void   normalize(void)    : garanti la coherence des donnees
      
    la methode "normalize" assure que les proprietes cls de l'objet sont
    bien du type attendu; par exemple que 'enabled' est bien une valeur
    booleene. Il n'est pas necessaire d'explicitement appeler cette
    methode, celle ci etant automatiquement appelle lors de la modification
    d'une propriet cl.
    
      bool   isValid(void)
      bool   isEmpty(void)      DEPRECATED, remplace par __nonzero__
      bool   isCompatibleWith(string aType)
   
    Une tache est jugee valide lorsque tout les proprietes obligatoires;
    Pour specifier quelles proprietes sont obligatoires, il faut surcharger
    la methode "isValid".
    
    "isEmpty", tel que sont nom l'indique, determine si au moins une
    propriete est definie.
    Nota: toutes les taches definissent obligatoirement une valeur pour la
    propriete "enabled", celle ci n'est donc pas consideree par la methode
    "isEmpty".
    
    "isCompatibleWith" indique si la tache est compatible avec le type
    propose. Une tache est au moins compatible avec son propre type.
    e.g.
      aTask.isCompatibleWith(aTask.tasktype)
      => True
   
      void   reset(void)
    
    Reinitialise la tache, une tache reinitialis est vide.
    e.g.
      aTask.reset()
      bool(aTask)
      => False
   
    Nota :
      "reset()" dispose d'un parametre optionnel "force" qu'il convient
      de ne pas employer en dehors d'un usage interne a la classe. En
      effet, "reset" est aussi utilis pour (re)creer les proprietes cls
      manquantes definies par la liste "attributes". L'heritage a oblig a
      l'ajout de ce parametre.
   
      void   assign(object source)
   
    copie l'integralite des proprietes de la source vers l'objet courant.
    
      void   fromList(list aList, string listType)
      void   toList(list aList, bool filtered)
      list   getAsList(bool filtered)
   
    Routines de conversion de tache en liste et vice-versa; les listes ont
    le format suivant: [(key, val), (key, val), .... ]
    pour "toList" et "getAsList", Si "filtered" est mis a True, alors les
    valeurs nulles (None) de la tache ne sont pas ajoutees a la liste.
    Dans tout les cas, une tache vide renvoie au moins une liste composee
    de son type et de son etat (actif ou non).
   
      object mergeWithList(list aList, bool force, string listType)
      object mergeWithTask(object task, bool force)
   
    Fusion de la tache courante avec une autre tache ou une liste (par
    exemple issue d'une autre tache). Ces methodes creent un nouvel objet
    qui est a la base une copy complete (deep copy) de l'objet courant.
    Les proprietes nulles (valant None) sont remplacees par celles de la
    source (tache ou liste).
    
    Cas particuliers, les proprietes "enabled", "comments", celles-ci ne
    seront remplacees si leur valeurs est nulles ET SI le parametre 'force'
    est mis a True (il serait handicapant que ces deux proprietes soient
    systematiquement remplacees)
    
    Si la tache, ou la liste, n'est pas reconnue compatible, alors seules
    les proprietes de bases ('enabled', 'logfile' et 'comments') sont
    susceptibles de se voir ecrasees (avec le meme fonctionnement que
    decris plus haut).
   
      object toCmdLine(void)
    
    Renvoie la ligne de commande a passer au systeme. une tache non valide
    renvoie une commande "vide". le resultat est un objet du type
    "asqCmdLine" (globalement identique a une liste).
    
      void   expandPaths(void)
      void   completePaths(string base)
   
    Traitement des proprietes definissant un chemin vers un fichier.
    - "expandPaths" applique "expandvars()", "normpath()" "normcase()"
      sur les proprietes reconnues comme chemins
    - "completePaths" assure que tout les chemins sont sous forme absolue



  * taskList (une liste de taches)
    Une taskList derive a la fois d'une liste et de la classe taskItem.
    Elle en reprend donc toutes les proprietes et methodes de ses ancetres,
    en imposant les regles suivantes:
    - Une liste de taches ne peut pas etre convertie en ligne de commande
    - les proprietes ne peuvent etre de valeur nulles, la valeur None est
     remplacee par une chaine vide
    
    De plus une liste de tache sera consideree comme vide si a la fois aucune
    de ses proprietes n'est renseignee (chaine vide), et si elle ne comporte
    aucun elements.
    
    
  ** methodes
   
      object appendNewTask(bool enabled)
    
    Cree une nouvelle tache et l'ajoute a la liste; "enabled" determine si
    la nouvelle tache est active ou non. Cette methode doit imperativement
    etre surchargee dans les classes derivant de taskList, en effet la
    methode definie pour taskList leve une exception



  * basicCommand
    la classe "commande" sert a executer les commandes/actions representees
    par les taches; ainsi chaque type de tache dispose de sa propre commande,
    plus a meme de gerer les particularites de la tache.
    
    Les commandes derivent de la classe windowsCmd, et sont donc hautement
    specifique a l'environnement Microsoft Windows.
    
    
  ** proprietes
   
    chaque commande dispose des proprietes suivantes, heritees de la classe
    windowsCmd
    
      list   listeners : liste de flux/fichiers de sortie
      string cmdOutput : resultat de la derniere commande passee au systeme
      object timestamp : instant de la derniere commande passee au systeme
    
    les "listeners" sont des objet se comportant comme des objets fichiers,
    au moins, il doit etre possible d'y ecrire quelque chose "write()"
    A chaque execution d'une tache, l'instant, la ligne de commande, et le
    resultat (stdout/stderr) sont ecrit dans chaque element de la liste
    "listeners"
    Les objets en double de la liste des listeners, ne recoivent qu'une
    seule fois un 'message'
    
    e.g. sur chaque elemet de la liste listeners sera ecrit :
      Thursday, 18 Nov 2004 19:30:00
      "c:\program files\borland\delphi7\bin\dcc32.exe"
       "d:\build\netasq\commonlib\src\debug\src\a_ndebug.dpr" "-Ed:\build\bin"
       "-Nd:\build\dcu" -B -Q
      Borland Delphi Version 15.0
      Copyright (c) 1983,2002 Borland Software Corporation
      Fatale: Fichier non trouv :
       'd:\build\netasq\commonlib\src\debug\src\a_ndebug.dpr'
    
    "cmdOutput" ne stocke que le resultat renvoy (stdout/stderr)  par le
    systeme a l'issue de la derniere execution de commande; tres pratique
    pour remonter la derniere erreur.
    
    e.g.
      Thursday, 18 Nov 2004 19:30:00
      "c:\program files\borland\delphi7\bin\dcc32.exe"
       "d:\build\netasq\commonlib\src\debug\src\a_ndebug.dpr" "-Ed:\build\bin"
       "-Nd:\build\dcu" -B -Q
      Borland Delphi Version 15.0
      Copyright (c) 1983,2002 Borland Software Corporation
      Fatale: Fichier non trouv :
       'd:\build\netasq\commonlib\src\debug\src\a_ndebug.dpr'
    
    "timestamp" est un objet "datetime" conservant l'instant de la derniere
    execution.
    
    e.g.
      timestamp.strftime
      => Thursday, 18 Nov 2004 19:30:00
    
    Une propriete supplementaire est disponible
    
      object task
    
    correspondant a la tache, un taskItem, execut/a executer. Le type de
    cette tache est defini par avance, et ne peux etre modifie: une commande
    d'un type donnee ne sait gerer QUE le type de tache correpondant.
    les affectations vers cette propriete sont transformees de la maniere
    suivante :
    
      aCmd.task = otherTask
      => aCmd.task.assign(otherTask)
   
    il n'y a donc pas copie d'une reference d'objet taskItem.
   
    
  ** methodes
    
    chaque commande dispose des methodes suivantes :
   
      void   clearListeners(void)
      void   clearTimeStamp(void)
    
    aux noms suffisemment explicites pour ne pas en parler davantage.
    La methode run() tel que definie par la classe windowsCmd
    
      var    run(string command, string codepage)
    
    est remplac par le prototype suivant
    
      var    run(object task, string codepage)
    
    qui ordonne l'execution de l'action definie par la tache courante; si
    le parametre "task" est non nul (not None), alors le parametre supplante
    la tache courante (aCmd.task = task) avant execution.
   
    "run" retourne None dans le cas d'une execution sans erreur, ou la
    valeur d'erreur retournee par le systeme (generalement 1)
   
    A savoir : la classe "basicCommand" decoupe l'execution en trois parties
    successives.
    
      void   _setUp(void)
      var    _run(string command, string codepage)
      void   _tearDown(void)
   
    qui correspondent aux etapes suivantes, respectivement
    - preparations avant execution
    - execution effective
    - "nettoyage" des preparatifs
   
    Lorsque la tache courante definie un fichier de traces (propriete
    logfile);
    - le fichier correspondant est ouvert en ecriture puis ajout a la liste
     des listeners par la methode "_setUp()"
    - apres execution, l'objet fichier est retir de la liste des listeners
     par la methode "_tearDown()"

